Amazon DynamoDBのUpdateItemでのif_not_exists構文の使いどころを確認してみた
こんにちは、CX事業本部 IoT事業部の若槻です。
Amazon DynamoDBではアイテム更新(UpdateItem
)時にAttributeの上書きを防止するための機能があります。
If you want to avoid overwriting an existing attribute, you can use
SET
with theif_not_exists
function. (The function name is case sensitive.) Theif_not_exists
function is specific to theSET
action and can only be used in an update expression. The syntax is as follows.-
if_not_exists (path, value)
If the item does not contain an attribute at the specified
path
,if_not_exists
evaluates to value; otherwise, it evaluates topath
.
第一引数に指定したパスのAttributeがアイテムに未設定であれば、第二引数に指定した値で置き換えるというものです。
今回は、このif_not_exists
構文を利用するパターンをいくつか試して、使いどころを確認してみました。
環境準備
sampleTable
テーブル作成。
aws dynamodb create-table \ --table-name sampleTable \ --attribute-definitions AttributeName=id,AttributeType=S \ --key-schema AttributeName=id,KeyType=HASH \ --billing-mode PAY_PER_REQUEST
アイテム作成。
aws dynamodb put-item --table-name sampleTable --item '{"id":{"S":"s001"}}' aws dynamodb put-item --table-name sampleTable --item '{"id":{"S":"s002"}}' aws dynamodb put-item --table-name sampleTable --item '{"id":{"S":"s003"}}'
if_not_exists構文を使う
値の設定
SET path = if_not_exists (path, value)
というUpdateExpressionの場合。
Attribute(username
)が未設定の場合、指定した値(mesoko
)が設定されました。
$ aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s001"}}' \ --update-expression "SET username = if_not_exists(username, :n)" \ --expression-attribute-values '{":n": {"S": "mesoko"}}' \ --return-values ALL_NEW { "Attributes": { "id": { "S": "s001" }, "username": { "S": "mesoko" } } }
Attribute(username
)が設定済みの場合も、指定した値(mesoko2
)が設定されませんでした。
$ aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s001"}}' \ --update-expression "SET username = if_not_exists(username, :n)" \ --expression-attribute-values '{":n": {"S": "mesoko2"}}' \ --return-values ALL_NEW { "Attributes": { "id": { "S": "s001" }, "username": { "S": "mesoko" } } }
Attributeが未設定の場合のみ更新されるという、上書き防止の動作を確認することができました。
ちなみにSET path = value
とすれば、Attributeが設定済みであるか未設定であるかに関わらず、指定の値を設定できました。
aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s001"}}' \ --update-expression "SET username2 = :n" \ --expression-attribute-values '{":n": {"S": "mesoko2"}}' \ --return-values ALL_NEW { "Attributes": { "username": { "S": "mesoko" }, "username2": { "S": "mesoko2" }, "id": { "S": "s001" } } }
数値加算
SET path = if_not_exists (path, value) + value2
という数値加算を行うUpdateExpressionの場合。
Attribute(price
)が未設定の場合、if_not_exists
の第二引数(:i
) + 加算数(:p
)の値で更新されました。
$ aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s002"}}' \ --update-expression "SET price = if_not_exists(price, :i) + :p" \ --expression-attribute-values '{":p": {"N": "100"}, ":i": {"N": "10"}}' \ --return-values ALL_NEW { "Attributes": { "id": { "S": "s002" }, "price": { "N": "110" } } }
Attribute(price
)が設定済みの場合、if_not_exists
の第一引数(price
) + 加算数(:p
)の値で更新されました。
$ aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s002"}}' \ --update-expression "SET price = if_not_exists(price, :i) + :p" \ --expression-attribute-values '{":p": {"N": "100"}, ":i": {"N": "10"}}' \ --return-values ALL_NEW { "Attributes": { "id": { "S": "s002" }, "price": { "N": "210" } } }
数値加算では、Attributeが未設定の場合に、加算される数に既定値が使用される動作を確認できました。
リストへの要素追加
SET path = list_append(if_not_exists (path, value), value2)
というリストへの要素追加を行うUpdateExpressionの場合。
Attribute(office_list
)が未設定の場合、if_not_exists
の第二引数(:init_list
)に要素(:e
)が追加されました。
$ aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s003"}}' \ --update-expression "SET office_list = list_append(if_not_exists(office_list, :init_list), :e)" \ --expression-attribute-values '{":init_list": {"L": [{"S": "sakuma"}]}, ":e": {"L": [{"S": "iwamoto-cho"}]}}' \ --return-values ALL_NEW { "Attributes": { "id": { "S": "s003" }, "office_list": { "L": [ { "S": "sakuma" }, { "S": "iwamoto-cho" } ] } } }
Attribute(office_list
)が設定済みの場合、if_not_exists
の第一引数(office_list
)に要素(:e
)が追加されました。
$ aws dynamodb update-item \ --table-name sampleTable \ --key '{"id":{"S":"s003"}}' \ --update-expression "SET office_list = list_append(if_not_exists(office_list, :init_list), :e)" \ --expression-attribute-values '{":init_list": {"L": [{"S": "sakuma"}]}, ":e": {"L": [{"S": "hibiya"}]}}' \ --return-values ALL_NEW { "Attributes": { "id": { "S": "s003" }, "office_list": { "L": [ { "S": "sakuma" }, { "S": "iwamoto-cho" }, { "S": "hibiya" } ] } } }
リストへの要素追加では、Attributeが未設定の場合に、追加されるリストに既定値が使用される動作を確認できました。
後始末
テーブル削除。
aws dynamodb delete-table --table-name sampleTable
おわりに
Amazon DynamoDBのUpdateItemでのif_not_exists構文の使いどころを確認してみました。
Attributeが未設定の場合を考慮する必要がある場合に役に立ちそうです。
参考
- create-table — AWS CLI 2.9.6 Command Reference
- put-item — AWS CLI 2.9.6 Command Reference
- DynamoDBでデータを更新する際に使うUpdateExpressionについて一通りまとめてみた | DevelopersIO
- amazon dynamodb - Is it possible to combine if_not_exists and list_append in update_item - Stack Overflow
以上